﻿using System;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.VisualStudio.SharePoint.Commands;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Linq;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;
using ServerExplorer.SharePointConnections.SharepointSiteInfo.Entities;


namespace ServerExplorer.SharePointConnections.SharepointSiteInfo
{
    internal class SharepointSiteInfoCommands
    {
        private static List<SPWeb> SiteInfoAllWebs = null;

        // Determines whether the specified solution has been deployed to the local SharePoint server.
        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSiteInfo)]
        public static Entities.SiteInfo[] GetSharepointSiteInfo(ISharePointCommandContext context)
        {
            try
            {
                List<Entities.SiteInfo> infoRequest = new List<Entities.SiteInfo>();
                SPSite site = context.Site;
                SPWeb web = site.OpenWeb();
                SPListCollection lists = web.Lists;
                foreach (CultureInfo culture in web.SupportedUICultures)
                {
                    Entities.SiteInfo siteInfo = new Entities.SiteInfo(culture);
                    infoRequest.Add(siteInfo);
                    Thread.CurrentThread.CurrentUICulture = culture;
                    foreach (SPList li in lists)
                    {
                        Entities.SiteInfoList listInfo = new Entities.SiteInfoList()
                        {
                            Title = li.Title,
                            Url = li.RootFolder.ServerRelativeUrl.ToString(),
                            ItemsCount = li.ItemCount.ToString(),
                            Description = li.Description,
                            FieldsCount = li.Fields.Count.ToString(),
                            EventReceiversCount = li.EventReceivers.Count.ToString(),
                            Guid = li.ID.ToString()
                        };
                        siteInfo.SiteLists.Add(listInfo);

                        foreach (SPEventReceiverDefinition er in li.EventReceivers)
                        {
                            Entities.SiteInfoEventReceiver eReceiver = new Entities.SiteInfoEventReceiver()
                            {
                                EventClass = er.Class
                            };
                            listInfo.SiteEventReceivers.Add(eReceiver);
                        }
                    }
                }
                return infoRequest.ToArray();
            }
            catch
            {
                return null;
            }
        }

        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSiteFieldInfo)]
        public static Entities.SiteInfoField[] GetSharepointSiteFieldInfo(ISharePointCommandContext context, string[] arg)
        {
            try
            {
                Guid guid = new Guid(arg[0]);
                CultureInfo culture = new CultureInfo(arg[1]);
                List<Entities.SiteInfoField> infoRequest = new List<Entities.SiteInfoField>();
                SPSite site = context.Site;
                SPWeb web = site.OpenWeb();
                SPList list = web.Lists[guid];
                Thread.CurrentThread.CurrentUICulture = culture;
                foreach (SPField f in list.Fields)
                {
                    Entities.SiteInfoField fieldNode = new Entities.SiteInfoField()
                    {
                        InternalName = f.InternalName,
                        Title = f.Title,
                        TypeAsString = f.TypeAsString,
                        TypeDisplayName = f.TypeDisplayName
                    };
                    infoRequest.Add(fieldNode);
                }
                return infoRequest.ToArray();
            }
            catch
            {
                return null;
            }
        }

        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSiteRootInfo)]
        public static SiteStructInfo GetSharepointSiteRootInfo(ISharePointCommandContext context)
        {
            SiteStructInfo wpInfo = new Entities.SiteStructInfo();
            List<Web> auxSiteInfoAllWebs = new List<Web>();
            try
            {
                SPSite site = context.Site;
                wpInfo.SiteName = site.Url;

                SiteInfoAllWebs = site.AllWebs.ToList<SPWeb>().OrderBy(o => o.ServerRelativeUrl).OrderBy(o => o.ParentWebId).ToList();

                foreach (SPWeb web in SiteInfoAllWebs)
                {
                    InsertIntoSiteInfoWeb(web, auxSiteInfoAllWebs);
                }

                wpInfo.RootWeb = auxSiteInfoAllWebs.Where(w => w.IsRootWeb).FirstOrDefault();
            }
            catch (Exception er)
            {
                throw new Exception(er.Message + "|" + SiteInfoAllWebs.Count.ToString());
            }
            return wpInfo;
        }

        private static void InsertIntoSiteInfoWeb(SPWeb web, List<Web> refList)
        {
            Web lWeb = null;

            if ((lWeb = refList.Where(w => (w.Guid.Equals(web.ID.ToString()))).FirstOrDefault()) == null)
            {
                lWeb = new Web();
                lWeb.WebURL = web.Url;
                lWeb.Guid = web.ID.ToString();
                lWeb.FolderName = (lWeb.IsRootWeb = web.IsRootWeb) ? web.Title : web.Name;
                refList.Add(lWeb);
            }

            List<SPWeb> subWebs = web.Webs.OfType<SPWeb>().ToList();
            if (subWebs.Count > 0)
            {
                lWeb.SubSites.Webs.AddRange(subWebs.Select(s => (Web)(new String[] { s.Name, s.Url, s.ID.ToString() })));
            }
            refList.AddRange(lWeb.SubSites.Webs);

            List<SPFolder> folderCollection = web.Folders.OfType<SPFolder>().ToList();
            if (folderCollection.Count > 0)
            {
                lWeb.Folders.AddRange(folderCollection.Select(s => (Folder)(new String[] { s.Name, s.UniqueId.ToString() })));
            }

            List<SPFile> filesCollection = web.Files.OfType<SPFile>().Where(w => Path.GetExtension(w.Name).Equals(".aspx")).ToList();
            if (filesCollection.Count > 0)
            {
                lWeb.Pages.AddRange(filesCollection.Select(s => (Page)(s.Url)));
            }
        }

        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSiteSubSite)]
        public static List<Web> GetSharepointSiteSubSite(ISharePointCommandContext context, string parameter)
        {
            List<Web> subSites = new List<Web>();
            try
            {
                SPSite site = context.Site;
                SPWeb webCol = site.AllWebs[new Guid(parameter)];
                SPWebCollection subWebs = webCol.Webs;
                subSites.AddRange(subWebs.OfType<SPWeb>().Select(s => (Web)(new String[] { s.Name, s.Url, s.ID.ToString() })));
            }
            catch
            {
                subSites = null;
            }
            return subSites;
        }


        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSitewebPartInfoFiles)]
        public static FolderFiles GetSharepointSitewebPartInfoFiles(ISharePointCommandContext context, String[] parameters)
        {
            FolderFiles folderFiles = new FolderFiles();
            try
            {
                SPSite site = context.Site;
                SPWeb webCol = site.AllWebs[new Guid(parameters[0])];
                SPFolderCollection folders = null;
                SPFileCollection files = null;
                SPFolder folder = webCol.GetFolder(new Guid(parameters[1]));
                folders = folder.SubFolders;
                files = folder.Files;

                if (folders.Count > 0)
                {
                    folderFiles.Folders.AddRange(folders.OfType<SPFolder>().Select(s => (Folder)(new String[] { s.Name, s.UniqueId.ToString() })));
                }

                if (files.Count > 0)
                {
                    folderFiles.Pages.AddRange(files.OfType<SPFile>().Where(w => Path.GetExtension(w.Name).Equals(".aspx")).Select(s => (Page)(s.Url)));
                }
            }
            catch
            {
                folderFiles.Folders = null;
                folderFiles.Pages = null;
            }
            return (folderFiles.Folders.Count == 0 && folderFiles.Pages.Count == 0) ? null : folderFiles;
        }


        [SharePointCommand(SharepointSiteInfoCommandsIDs.GetSharepointSitewebPartInfo)]
        public static List<WebPartInfo> GetSharepointSitewebPartInfo(ISharePointCommandContext context, String[] parameters)
        {
            List<WebPartInfo> webParts = new List<WebPartInfo>();
            try
            {
                SPSite site = context.Site;
                SPWeb web = site.AllWebs[new Guid(parameters[0])];
                SPLimitedWebPartManager wpMan = web.GetLimitedWebPartManager(parameters[1], PersonalizationScope.Shared);
                SPLimitedWebPartCollection wpCollection = wpMan.WebParts;
                if (wpCollection.Count > 0)
                {
                    webParts.AddRange(
                        wpCollection.OfType<System.Web.UI.WebControls.WebParts.WebPart>().Select(s =>
                        (WebPartInfo)(string.Format("{0}({1}):{2}:{3}:{4}",
                        s.GetType().Name, s.GetType().Namespace,
                        !String.IsNullOrEmpty(s.Title) ? s.Title : !string.IsNullOrEmpty(s.DisplayTitle) ? s.DisplayTitle : s.ID,
                        parameters[1], s.IsClosed ? "N" : "S"))));
                }
                else
                {
                    string none = String.Format("{0}:{1}:{2}:{3}", "(None)", "(None)", parameters[1], "B");
                    webParts.Add((WebPartInfo)none);
                }
            }
            catch
            {
                string none = String.Format("{0}:{1}:{2}:{3}", "(None)", "(None)", parameters[1], "B");
                webParts.Add((WebPartInfo)none);
            }
            return webParts;
        }
    }
}
